#ifndef _WALLCLOCK
#define _WALLCLOCK

// GENERAL INCLUDES ------------------------------------------------------------------------------------------
#include "Base.h"

// FUNCTIONS -------------------------------------------------------------------------------------------------

// retrieve elapsed time in milliseconds
ui64 TimeMs();

// stopwatch function for measuring time intervals in milliseconds -------------------------------------------

// START watch X, resetting marked time
void TimeStopwatchStart(ui32 watch);

/* STOP watch X, return elapsed millisecond difference
   -> returns zero if watch X hasn't been started via timeStopwatchStart() */
ui64 TimeStopwatchStop(ui32 watch);

// TODO: profiling einbauen

/*
PROFILE_START(function, logIndividualRuns);
PROFILE_STOP(function);

// ------------------------------ TIMER CLOCKBOARD ------------------------------------------------
// our clockboard and the associated time clips
public class timeClip
{
    public TimeSpan lastStart = new TimeSpan(),      // last time-index task was started
                    lastRuntime = new TimeSpan(),    // last runtime of successful task completion
                    lastStall = new TimeSpan(),      // runtime difference between this and last task completion
                    stallInTotal = new TimeSpan(),   // runtime stall in TOTAL for this task
                    runtimeInTotal = new TimeSpan(), // runtime in TOTAL for this task
                    runtimeAverage = new TimeSpan();

    public int called = 0;

    public int calledWithoutStart = 0; // is marked if Stop() without start for key X is found
    public int calledWithoutStop = 0;  // is marked if Start() without stop for key X is found

    // log individual runtimes of single Start/Stop combinations
    public bool logIndividualRuns = false;
    public List<TimeSpan> individualRuntime = new List<TimeSpan>();
}
public static Dictionary<string, timeClip> clockBoard = new Dictionary<string, timeClip>();

public static int UpdateIsStalling = 0,
                  DrawIsStalling = 0;

public static void WatchStart(string k) { WatchStart(k, false); }
public static void WatchStart(string k, bool _logIndividualRuns)
{
    // if the task doesn't exist yet, add it
    if (!clockBoard.ContainsKey(k))
    {
        // create a new timeclip
        timeClip newClip = new timeClip();
        newClip.logIndividualRuns = _logIndividualRuns;
        // add it
        clockBoard.Add(k, newClip);
    }

    timeClip t = clockBoard[k];

    // check for Re-Start() without Stop()
    if (t.lastStart != TimeSpan.Zero)
    {
        // whoops! A _new_ Start() was called before a stop was issued.
        // user-error, so add up the time and restart it
        t.runtimeInTotal +=
            new TimeSpan(DateTime.Now.Ticks - t.lastStart.Ticks);

        // mark it up as DUMBASS
        t.calledWithoutStop++;
    }
    // start it's clock!
    t.lastStart = new TimeSpan(DateTime.Now.Ticks);
}

public static void WatchStop(string k)
{
    // only add up tasks that we already got on the board...
    if (clockBoard.ContainsKey(k))
    {
        // get timeclip X
        timeClip t = clockBoard[k];
        // stop the clock
        TimeSpan now = new TimeSpan(DateTime.Now.Ticks - t.lastStart.Ticks);

        // if log of individual runs is ON, log this run's time
        if (t.logIndividualRuns == true) t.individualRuntime.Add(now);

        // add up the task
        t.runtimeInTotal += now;

        // calculate stall-time. minus -> this time fast, plus -> this time slower
        TimeSpan stall = t.lastRuntime - now;
        // if stall is in the plus, save it
        if (stall > TimeSpan.Zero)
        {
            t.lastStall = stall;     // save stall of this iteration
            t.stallInTotal += stall; // save up overall stall of this task
        }
        else
        {
            if (t.lastStall != TimeSpan.Zero) t.lastStall = TimeSpan.Zero;
        }

        // save last runtime
        t.lastRuntime = now;
        // reset last start time
        t.lastStart = TimeSpan.Zero;
        // add up amount of calls
        t.called++;

        // calculate a new average
        t.runtimeAverage = new TimeSpan(t.runtimeInTotal.Ticks / t.called);
    }
    else
    {
        // add it up, but mark it as "called without start" -> essentually a user-error
        clockBoard.Add(k, new timeClip());
        clockBoard[k].calledWithoutStart++;
    }
}

// display timing informations
public static void WatchShowClockboard()
{
    int y = Global.SCREEN_HEIGHT - 140;

    HL.G2DSpriteRenderBegin();
        foreach (string k in clockBoard.Keys)
        {
            timeClip t = clockBoard[k];

            float average = (float)t.runtimeAverage.TotalMilliseconds,
                  lastStall = (float)t.lastStall.TotalMilliseconds,
                  stallTotal = (float)t.stallInTotal.TotalMilliseconds;

            string line = "total: " + t.runtimeInTotal + ", " +
                          String.Format(
                            "average {0:f3}, stall {0:f3}, sTotal {0:f3}",
                            average, lastStall, stallTotal
                          ) +
                          " -> " + k;

            HL.WriteText(5, y += 16, line, Color.Red, 1.0f);
        }

    // display amount of rendered polygons and check if game is running slow and dropping frames
    HL.WriteText(
        5, y += 16,
        "Polygons on Screen=" + HL.amountOfRenderPolygons +
        ", FPS: " + HL_FrameWork.currentFramerate +
        ", UpdateIsStalling=" + UpdateIsStalling +
        ", DrawIsStalling=" + DrawIsStalling,
        Color.Red, 1.0f
    );

    HL.G2DSpriteRenderEnd();
}
*/

#endif // _WALLCLOCK
